package com.yzxb.erpsystem.service.impl;

import com.yzxb.erpsystem.entity.Product;
import com.yzxb.erpsystem.mapper.ProductMapper;
import com.yzxb.erpsystem.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

@Service
public class ProductServiceImpl implements ProductService {

    // --- 1. 定义缓存 Key 的前缀和常量 ---
    private static final String PRODUCT_KEY_PREFIX = "product:";
    private static final String ALL_PRODUCTS_KEY = "all_products";

    // --- 2. 优化过期时间策略，防止缓存雪崩 ---
    private static final long CACHE_EXPIRATION_SECONDS = TimeUnit.HOURS.toSeconds(24); // 基础过期时间：24小时
    private static final long CACHE_RANDOM_RANGE_SECONDS = TimeUnit.HOURS.toSeconds(2);   // 随机范围：2小时

    /**
     * 【关键】注入 RedisTemplate 时必须指定泛型 <String, Object>
     */
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private ProductMapper productMapper;

    // 辅助方法，用于生成单个商品的 key
    private String getProductKey(Long id) {
        return PRODUCT_KEY_PREFIX + id;
    }

    // 辅助方法，获取带随机抖动的过期时间（秒）
    private long getRandomizedExpiration() {
        return CACHE_EXPIRATION_SECONDS + (long) (Math.random() * CACHE_RANDOM_RANGE_SECONDS);
    }

    @Override
    @Transactional
    public Product createProduct(Product product) {
        // 非空校验
        if (product == null) {
            throw new IllegalArgumentException("商品信息不能为空");
        }
        if (product.getProductCode() == null || product.getProductCode().trim().isEmpty()) {
            throw new IllegalArgumentException("商品编码不能为空");
        }
        if (product.getProductName() == null || product.getProductName().trim().isEmpty()) {
            throw new IllegalArgumentException("商品名称不能为空");
        }
        if (product.getCategoryId() == null) {
            throw new IllegalArgumentException("分类ID不能为空");
        }
        if (product.getUnit() == null || product.getUnit().trim().isEmpty()) {
            throw new IllegalArgumentException("单位不能为空");
        }
        if (productMapper.selectByProductCode(product.getProductCode()) != null) {
            throw new IllegalArgumentException("商品编码已存在");
        }
        if (product.getCostPrice() == null) {
            product.setCostPrice(BigDecimal.ZERO);
        }
        if (product.getSalePrice() == null) {
            product.setSalePrice(BigDecimal.ZERO);
        }
        if (product.getStockQuantity() == null) {
            product.setStockQuantity(BigDecimal.ZERO);
        }
        LocalDateTime now = LocalDateTime.now();
        product.setCreatedTime(now);
        product.setUpdatedTime(now);
        if (product.getStatus() == null || product.getStatus().trim().isEmpty()) {
            product.setStatus("ACTIVE");
        }
        int rows = productMapper.insert(product);
        if (rows != 1) {
            throw new RuntimeException("创建商品失败");
        }
        Product createdProduct = productMapper.selectById(product.getId());

        // 缓存操作：创建了新商品，列表缓存必须删除
        deleteListCache();
        return createdProduct;
    }

    /**
     * 删除列表缓存的方法
     */
    private void deleteListCache() {
        redisTemplate.delete(ALL_PRODUCTS_KEY);
    }

    @Override
    @Transactional
    public void deleteProduct(Long id) {
        if (id == null) {
            throw new IllegalArgumentException("商品ID不能为空");
        }
        Product product = productMapper.selectById(id);
        if (product == null) {
            throw new IllegalArgumentException("商品不存在");
        }
        int rows = productMapper.deleteById(id);
        if (rows != 1) {
            throw new RuntimeException("删除商品失败");
        }
        // 缓存操作：删除了商品，必须同时删除单个缓存和列表缓存
        redisTemplate.delete(getProductKey(id));
        deleteListCache();
    }

    @Override
    @Transactional
    public Product updateProduct(Long id, Product product) {
        if (id == null) {
            throw new IllegalArgumentException("商品ID不能为空");
        }
        if (product == null) {
            throw new IllegalArgumentException("商品信息不能为空");
        }
        Product existingProduct = productMapper.selectById(id);
        if (existingProduct == null) {
            throw new IllegalArgumentException("商品不存在");
        }
        product.setId(id);
        product.setCreatedTime(existingProduct.getCreatedTime());
        product.setUpdatedTime(LocalDateTime.now());
        Product productByCode = productMapper.selectByProductCode(product.getProductCode());
        if (productByCode != null && !productByCode.getId().equals(id)) {
            throw new IllegalArgumentException("商品编码已存在");
        }
        int rows = productMapper.update(product);
        if (rows != 1) {
            throw new RuntimeException("更新商品失败");
        }
        Product updatedProduct = productMapper.selectById(id);

        // 缓存操作：更新了商品，必须更新单个缓存并删除列表缓存
        redisTemplate.opsForValue().set(getProductKey(id), updatedProduct, getRandomizedExpiration(), TimeUnit.SECONDS);
        deleteListCache();
        return updatedProduct;
    }

    @Override
    public Optional<Product> getProductById(Long id) {
        if (id == null) {
            return Optional.empty();
        }
        String key = getProductKey(id);

        // 1. 先从缓存中查找
        Product product = (Product) redisTemplate.opsForValue().get(key);
        if (product != null) {
            System.out.println("从缓存中获取ID为：" + id + "的产品..");
            return Optional.of(product);
        }

        // 2. 缓存未命中，从数据库查找
        System.out.println("从数据库查询 ID 为: " + id + " 的产品...");
        product = productMapper.selectById(id);

        // 3. 将结果存入缓存
        if (product != null) {
            redisTemplate.opsForValue().set(key, product, getRandomizedExpiration(), TimeUnit.SECONDS);
        } else {
            // 增加缓存穿透防护
            redisTemplate.opsForValue().set(key, null, 5, TimeUnit.MINUTES);
        }
        return Optional.ofNullable(product);
    }

    @Override
    public Optional<Product> getProductByProductCode(String productCode) {
        // 建议：此方法也可以像 getProductById 一样添加缓存逻辑，
        // Key 可以是 "product:code:" + productCode
        if (productCode == null || productCode.trim().isEmpty()) {
            return Optional.empty();
        }
        Product product = productMapper.selectByProductCode(productCode);
        return Optional.ofNullable(product);
    }

    @Override
    public List<Product> getAllProducts() {
        // 1. 先从缓存中查找
        List<Product> productList = (List<Product>) redisTemplate.opsForValue().get(ALL_PRODUCTS_KEY);
        if (productList != null) {
            System.out.println("从缓存中获取所有产品列表...");
            return productList;
        }
        // 2. 缓存未命中，从数据库查找
        System.out.println("从数据库查询所有产品列表...");
        productList = productMapper.selectAll();

        // 3. 将结果存入缓存
        if (productList != null && !productList.isEmpty()) {
            redisTemplate.opsForValue().set(ALL_PRODUCTS_KEY, productList, getRandomizedExpiration(), TimeUnit.SECONDS);
        }
        return productList;
    }

    @Override
    public List<Product> getProductsByStatus(String status) {
        if (status == null || status.trim().isEmpty()) {
            return getAllProducts();
        }
        return productMapper.selectByStatus(status);
    }

    @Override
    public List<Product> getProductsByCategoryId(Long categoryId) {
        return getAllProducts();
    }

    @Override
    @Transactional
    public Product activateProduct(Long id) {
        Product product = getProductById(id)
                .orElseThrow(() -> new IllegalArgumentException("商品不存在"));

        product.setStatus("ACTIVE");
        product.setUpdatedTime(LocalDateTime.now());

        int rows = productMapper.update(product);
        if (rows != 1) {
            throw new RuntimeException("上架商品失败");
        }

        // 为 activate/deactivate 方法添加缓存同步逻辑
        redisTemplate.opsForValue().set(getProductKey(id), product, getRandomizedExpiration(), TimeUnit.SECONDS);
        deleteListCache();

        return product;
    }

    @Override
    @Transactional
    public Product deactivateProduct(Long id) {
        Product product = getProductById(id)
                .orElseThrow(() -> new IllegalArgumentException("商品不存在"));

        product.setStatus("INACTIVE");
        product.setUpdatedTime(LocalDateTime.now());

        int rows = productMapper.update(product);
        if (rows != 1) {
            throw new RuntimeException("下架商品失败");
        }

        // 同步缓存
        redisTemplate.opsForValue().set(getProductKey(id), product, getRandomizedExpiration(), TimeUnit.SECONDS);
        deleteListCache();

        return product;
    }
}